#include "npc_car.h"
#include "ltservershell.h"
#include "server_physics.h"
#include "msgids.h"
#include "AutoDriving.h"


namespace GameLogic {

    LTVector npc_car::do_position() const {
        LTVector position ;
        g_pLTServer->GetObjectPos(m_obj->GetHOBJECT(), &position) ;
        return position ;
    }

    LTRotation npc_car::do_rotation() const {
        LTRotation rot ;
        g_pLTServer->GetObjectRotation(m_obj->GetHOBJECT(), &rot) ;
        return rot ;
    }

    void npc_car::do_update_car_steer(float timeInteval) {  

    }

    HOBJECT npc_car::do_get_object() {
        return m_obj->GetHOBJECT() ;
    }
    
    void npc_car::do_update_pos_rotation() {
        server_physics* physics = m_logic_shell->physics_system();
        hkVector4 pos = physics->car_position(id()) ;
        const hkQuaternion& rot = physics->car_rotation(id()) ;
        LTVector jpos(pos(0), pos(1), pos(2)) ;
        jpos = m_logic_shell->physics_position_transfer_to_game_position(jpos) ;
        LTRotation jrot(rot(0), rot(1), rot(2), rot(3)) ;
        jrot = m_logic_shell->physics_rotation_transfer_to_game_rotation(jrot) ;
        set_speed(physics->car_speed(id())) ;
        g_pLTServer->SetObjectPos(m_obj->GetHOBJECT(), &jpos) ;
        g_pLTServer->SetObjectRotation(m_obj->GetHOBJECT(), &jrot) ;
    }

    npc_car::npc_car(int id, ILTBaseClass* obj, const char* className, racing_logic_shell* shell) 
      : car(id), m_obj(obj), m_className(className) , m_pAutoDriving(NULL),
        m_logic_shell(shell)
	{

	}

    npc_car::~npc_car()
	{
        if(m_obj)
		{
            HCLASS hClass = g_pLTServer->GetClass(m_className.c_str()) ;
            g_pLTServer->RemoveObject(hClass, m_obj) ;
            m_obj = 0 ;
        }

		if(m_pAutoDriving != NULL)
		{
			delete m_pAutoDriving;
			m_pAutoDriving = NULL;
		}
    }

	void npc_car::components_activation(void)
	{
		if (m_pAutoDriving == NULL) m_pAutoDriving = new AutoDriving;
	}

	void npc_car::update_steering()
	{
		Steering_Behavior_Interface* pSteeringBehaviorInterface = GetSingletonPointer(AI_Behavior)->get_steering_behavior();
		m_State.Position.set(position().x, position().z);
		m_State.Forward.set(rotation().Forward().x, rotation().Forward().z);
		m_State.Speed = speed();
		m_Parms.RoadPoint = &m_roadpoints;
		m_Parms.VehicleID = id();
		pSteeringBehaviorInterface->set_steering(m_State, m_Data, m_Parms);
		pSteeringBehaviorInterface->ok_lets_go();
	}

	void npc_car::update_steering_state_machine()
	{
		Steering_Behavior_Interface* pSteeringBehaviorInterface = GetSingletonPointer(AI_Behavior)->get_steering_behavior();
		AutoDriving::Parms autoDrivingParms;
		autoDrivingParms.CurrentSpeed = m_State.Speed;
		autoDrivingParms.FollowingPosition = pSteeringBehaviorInterface->get_following_position();
		autoDrivingParms.IsRoadPointOver = pSteeringBehaviorInterface->is_path_point_over();
		if(m_pAutoDriving != NULL)
		{
			AutoDriving::Result autoDrivingResult = m_pAutoDriving->get_result(autoDrivingParms, AutoDriving::Data());
			m_State.IsReverseSteering = autoDrivingResult.IsReverseRunning;
			m_State.IsWantToBrake = autoDrivingResult.IsBraking;
		}
	}

	void npc_car::do_update_action_logic()
	{
		components_activation();
		update_steering();
		update_steering_state_machine();
	}
}
